<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>计算机体系结构 | ChenDong Zhu&#39;s Blog</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noodp" />
<meta name="Description" content="备战龙芯杯&amp;关于计算机体系结构的学习"><link rel="prev" href="/2021/01/python%E5%8F%AF%E8%A7%86%E5%8C%96/" /><link rel="next" href="/2021/02/2021%E7%BE%8E%E8%B5%9B/" /><link rel="canonical" href="/2021/01/%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84/" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff"><meta property="og:title" content="计算机体系结构" />
<meta property="og:description" content="备战龙芯杯&amp;关于计算机体系结构的学习" />
<meta property="og:type" content="article" />
<meta property="og:url" content="/2021/01/%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84/" /><meta property="article:section" content="posts" />
<meta property="article:published_time" content="2021-01-16T09:00:00+08:00" />
<meta property="article:modified_time" content="2021-01-16T09:00:00+08:00" />

<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="计算机体系结构"/>
<meta name="twitter:description" content="备战龙芯杯&amp;关于计算机体系结构的学习"/>
<script type="application/ld+json">
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "计算机体系结构",
        "mainEntityOfPage": {
            "@type": "WebPage",
            "@id": "\/2021\/01\/%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84\/"
        },"image": {
                "@type": "ImageObject",
                "url": "\/cover.png",
                "width":  800 ,
                "height":  600 
            },"genre": "posts","keywords": "计算机体系结构","wordcount":  5402 ,
        "url": "\/2021\/01\/%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84\/","datePublished": "2021-01-16T09:00:00\u002b08:00","dateModified": "2021-01-16T09:00:00\u002b08:00","license": "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.","publisher": {
                "@type": "Organization",
                "name": "xxxx",
                "logo": {
                "@type": "ImageObject",
                "url": "\/logo.png",
                "width":  127 ,
                "height":  40 
                }
            },"description": "备战龙芯杯\u0026关于计算机体系结构的学习"
    }
    </script><link rel="stylesheet" href="/css/style.min.css"><link rel="stylesheet" href="/css/lib/fontawesome-free/all.min.css"><link rel="stylesheet" href="/css/lib/animate/animate.min.css"></head>
    <body><script>
            window.isDark = (window.localStorage && window.localStorage.getItem('theme')) === 'dark';
            window.isDark && document.body.classList.add('dark-theme');
        </script><div class="wrapper"><nav class="navbar">
    <div class="navbar-container">
        <div class="navbar-header animated bounceIn">
            <a href="/">ChenDong Zhu&#39;s Blog</a>
        </div>
        <div class="navbar-menu"><a class="menu-item" href="/posts" title="">文章</a><a class="menu-item" href="/tags" title="">标签</a><a class="menu-item" href="/categories" title="">分类</a><a class="menu-item" href="/about" title="">关于</a><a class="menu-item" href="https://hugo-loveit-en.netlify.com" title="English"><i class="fas fa-language fa-fw"></i></a><a href="javascript:void(0);" class="theme-switch"><i class="fas fa-adjust fa-rotate-180 fa-fw" title="切换主题"></i></a>
        </div>
    </div>
</nav><nav class="navbar-mobile">
    <div class="navbar-container">
        <div class="navbar-header">
            <div class="navbar-header-title animated bounceIn">
                <a href="/">ChenDong Zhu&#39;s Blog</a>
            </div>
            <div class="menu-toggle" id="menu-toggle">
                <span></span><span></span><span></span>
            </div>
        </div>
        <div class="navbar-menu" id="mobile-menu"><a class="menu-item" href="/posts" title="">文章</a><a class="menu-item" href="/tags" title="">标签</a><a class="menu-item" href="/categories" title="">分类</a><a class="menu-item" href="/about" title="">关于</a><a class="menu-item" href="https://hugo-loveit-en.netlify.com" title="English"></a><a href="javascript:void(0);" class="theme-switch"><i class="fas fa-adjust fa-rotate-180 fa-fw" title="切换主题"></i></a>
        </div>
    </div>
</nav><main class="main">
                <div class="container"><article class="page"><h1 class="post-title animated flipInX">计算机体系结构</h1><div class="post-meta">
            <div class="post-meta-main"><a class="author" href="/" rel="author" target="_blank">
                    <i class="fas fa-user-circle fa-fw"></i>ChenDong Zhu
                </a>&nbsp;<span class="post-category">收录于&nbsp;<i class="far fa-folder fa-fw"></i><a href="/categories/%E5%AD%A6%E4%B9%A0/">学习</a>&nbsp;</span></div>
            <div class="post-meta-other"><i class="far fa-calendar-alt fa-fw"></i><time datetime=2021-01-16>2021-01-16</time>&nbsp;
                <i class="fas fa-pencil-alt fa-fw"></i>约 5402 字&nbsp;
                <i class="far fa-clock fa-fw"></i>预计阅读 11 分钟&nbsp;</div>
        </div><div class="post-toc" id="post-toc">
                <h2 class="post-toc-title">目录</h2>
                <div class="post-toc-content"><nav id="TableOfContents">
  <ul>
    <li><a href="#计算机体系结构基础">《计算机体系结构基础》</a>
      <ul>
        <li><a href="#指令集架构">指令集架构</a>
          <ul>
            <li><a href="#地址空间">地址空间</a></li>
            <li><a href="#系统指令分类">系统指令分类</a></li>
            <li><a href="#操作数">操作数</a></li>
            <li><a href="#指令操作和编码">指令操作和编码</a></li>
            <li><a href="#各指令集特色">各指令集特色</a></li>
          </ul>
        </li>
        <li><a href="#异常与中断">异常与中断</a>
          <ul>
            <li><a href="#异常处理流程">异常处理流程</a></li>
            <li><a href="#中断">中断</a></li>
            <li><a href="#中断传递机制">中断传递机制</a></li>
          </ul>
        </li>
        <li><a href="#存储管理">存储管理</a>
          <ul>
            <li><a href="#mips地址空间布局">MIPS地址空间布局</a></li>
            <li><a href="#tlb的结构和使用">TLB的结构和使用</a></li>
            <li><a href="#tlb异常处理">TLB异常处理</a></li>
          </ul>
        </li>
        <li><a href="#软硬件协同">软硬件协同</a>
          <ul>
            <li><a href="#mips-abi-整数寄存器约定">MIPS ABI 整数寄存器约定</a></li>
            <li><a href="#mips堆栈布局">MIPS堆栈布局</a></li>
            <li><a href="#本章其他">本章其他</a></li>
          </ul>
        </li>
        <li><a href="#计算机组成原理和结构">计算机组成原理和结构</a>
          <ul>
            <li><a href="#冯诺依曼结构">冯·诺依曼结构</a></li>
            <li><a href="#存储器">存储器</a></li>
            <li><a href="#北桥和南桥">北桥和南桥</a></li>
          </ul>
        </li>
        <li><a href="#计算机总线接口技术">计算机总线接口技术</a>
          <ul>
            <li><a href="#总线分类">总线分类</a></li>
          </ul>
        </li>
        <li><a href="#简单运算器设计">简单运算器设计</a>
          <ul>
            <li><a href="#一位全加器">一位全加器</a></li>
            <li><a href="#行波进位加法器">行波进位加法器</a></li>
            <li><a href="#先行进位并行进位加法器">先行进位（并行进位）加法器</a></li>
            <li><a href="#减法器">减法器</a></li>
            <li><a href="#比较器">比较器</a></li>
            <li><a href="#移位器">移位器</a></li>
          </ul>
        </li>
        <li><a href="#定点补码乘法器">定点补码乘法器</a>
          <ul>
            <li><a href="#迭代式源码乘法器">迭代式源码乘法器</a></li>
            <li><a href="#font-colorredbooth乘法器font"><font color='red'>Booth乘法器</font></a></li>
            <li><a href="#font-colorred华莱士树wallace-treefont"><font color='red'>华莱士树（Wallace Tree）</font></a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="#自己动手写cpu">自己动手写CPU</a>
      <ul>
        <li><a href="#流水线相关">流水线相关</a></li>
        <li><a href="#译码">译码</a></li>
      </ul>
    </li>
  </ul>
</nav></div>
            </div>
            <div class="post-toc-mobile" id="post-toc-mobile">
                <details>
                    <summary>
                        <div class="post-toc-title">
                            <span>目录</span>
                            <span><i class="details icon fas fa-angle-down"></i></span>
                        </div>
                    </summary>
                    <div class="post-toc-content"><nav id="TableOfContentsMobile">
  <ul>
    <li><a href="#计算机体系结构基础">《计算机体系结构基础》</a>
      <ul>
        <li><a href="#指令集架构">指令集架构</a>
          <ul>
            <li><a href="#地址空间">地址空间</a></li>
            <li><a href="#系统指令分类">系统指令分类</a></li>
            <li><a href="#操作数">操作数</a></li>
            <li><a href="#指令操作和编码">指令操作和编码</a></li>
            <li><a href="#各指令集特色">各指令集特色</a></li>
          </ul>
        </li>
        <li><a href="#异常与中断">异常与中断</a>
          <ul>
            <li><a href="#异常处理流程">异常处理流程</a></li>
            <li><a href="#中断">中断</a></li>
            <li><a href="#中断传递机制">中断传递机制</a></li>
          </ul>
        </li>
        <li><a href="#存储管理">存储管理</a>
          <ul>
            <li><a href="#mips地址空间布局">MIPS地址空间布局</a></li>
            <li><a href="#tlb的结构和使用">TLB的结构和使用</a></li>
            <li><a href="#tlb异常处理">TLB异常处理</a></li>
          </ul>
        </li>
        <li><a href="#软硬件协同">软硬件协同</a>
          <ul>
            <li><a href="#mips-abi-整数寄存器约定">MIPS ABI 整数寄存器约定</a></li>
            <li><a href="#mips堆栈布局">MIPS堆栈布局</a></li>
            <li><a href="#本章其他">本章其他</a></li>
          </ul>
        </li>
        <li><a href="#计算机组成原理和结构">计算机组成原理和结构</a>
          <ul>
            <li><a href="#冯诺依曼结构">冯·诺依曼结构</a></li>
            <li><a href="#存储器">存储器</a></li>
            <li><a href="#北桥和南桥">北桥和南桥</a></li>
          </ul>
        </li>
        <li><a href="#计算机总线接口技术">计算机总线接口技术</a>
          <ul>
            <li><a href="#总线分类">总线分类</a></li>
          </ul>
        </li>
        <li><a href="#简单运算器设计">简单运算器设计</a>
          <ul>
            <li><a href="#一位全加器">一位全加器</a></li>
            <li><a href="#行波进位加法器">行波进位加法器</a></li>
            <li><a href="#先行进位并行进位加法器">先行进位（并行进位）加法器</a></li>
            <li><a href="#减法器">减法器</a></li>
            <li><a href="#比较器">比较器</a></li>
            <li><a href="#移位器">移位器</a></li>
          </ul>
        </li>
        <li><a href="#定点补码乘法器">定点补码乘法器</a>
          <ul>
            <li><a href="#迭代式源码乘法器">迭代式源码乘法器</a></li>
            <li><a href="#font-colorredbooth乘法器font"><font color='red'>Booth乘法器</font></a></li>
            <li><a href="#font-colorred华莱士树wallace-treefont"><font color='red'>华莱士树（Wallace Tree）</font></a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="#自己动手写cpu">自己动手写CPU</a>
      <ul>
        <li><a href="#流水线相关">流水线相关</a></li>
        <li><a href="#译码">译码</a></li>
      </ul>
    </li>
  </ul>
</nav></div>
                </details>
            </div><div class="post-content"><p>大三升大四的暑假遇见了龙芯杯，然而却因为各种事（创青春、挑战杯）耽搁了，最终弃赛，然深感这个比赛的有趣，大四的寒假开始，打算系统学习计算机体系结构，打算参赛今年的龙芯杯个人赛，如果在比赛前CPU的设计比较好，可以考虑带学弟参加团队赛。以下是对于官方推荐《计算机体系结构基础》的学习。</p>
<a class="post-dummy-target" id="计算机体系结构基础"></a><h2>《计算机体系结构基础》</h2>
<p>前两章算是导论和介绍，从第三章开始。</p>
<a class="post-dummy-target" id="指令集架构"></a><h3>指令集架构</h3>
<a class="post-dummy-target" id="地址空间"></a><h4>地址空间</h4>
<p>地址空间包括<strong>寄存器空间</strong>和<strong>系统内存空间</strong>，寄存器空间包括通用寄存器，特殊寄存器，控制寄存器。</p>
<ul>
<li>寄存器空间：
<ul>
<li>通用寄存器：现代MIPS处理器 包含32个整数通用寄存器和32个浮点通用寄存器，其编号分别表示为$0 ~ $31 和$f0 ~ $f31，其中$0总返回全0</li>
<li>特殊寄存器：有用于存放乘除法结果的HI、LO寄存器</li>
<li>控制寄存器：MIPS定义在协处理器0上</li>
</ul>
</li>
<li>内存空间：广义上分IO空间和内存空间，对于MIPS，两者都使用访存指令，对于X86实模式，对IO空间有专门的in/out指令</li>
</ul>
<a class="post-dummy-target" id="系统指令分类"></a><h4>系统指令分类</h4>
<ul>
<li>堆栈型：又称零地址指令。如 <em>PUSH A</em></li>
<li>累加器型：又称单地址指令，包含了一个隐含操作数——累加器，结果写回累加器。如 <em>ADD B</em></li>
<li>寄存器-存储器型：操作数显式指定，为寄存器或内存地址，如 <em>ADD R1, B</em></li>
<li>寄存器-寄存器型：操作时显式指定，除了访存外其他指令的操作数都为寄存器，如<em>ADD R3, R1, R2</em></li>
</ul>
<p>当今指令系统主要是寄存器-寄存器型，使用寄存器的优势在于</p>
<ul>
<li>寄存器访问速度块，便于编译器调度优化</li>
<li>可以利用局部性原理，大量操作在寄存器中完成</li>
<li>寄存器中的相关性容易判断，容易实现流水线、多发射、乱序执行</li>
</ul>
<a class="post-dummy-target" id="操作数"></a><h4>操作数</h4>
<ul>
<li>单浮点4字节，双精度浮点8字节</li>
<li>访存地址支持对齐访问和不对齐访问</li>
<li>常用寻址方式：寄存器寻址、立即数寻址&hellip;&hellip;</li>
</ul>
<a class="post-dummy-target" id="指令操作和编码"></a><h4>指令操作和编码</h4>
<p>功能上划分，指令分为四大类：运算指令、访存指令、转移指令、特殊指令</p>
<a class="post-dummy-target" id="各指令集特色"></a><h4>各指令集特色</h4>
<ul>
<li>MIPS：访问不对齐数据的指令：<em>LWL/LWR</em></li>
<li>SPARC：寄存器窗口，函数调用时可以不用进行保存现场，只需切换寄存器组</li>
<li>PA-RISE：Nullificatin指令</li>
<li>PowerPC：指令功能性强，被称为RISC中的CISC</li>
</ul>
<a class="post-dummy-target" id="异常与中断"></a><h3>异常与中断</h3>
<a class="post-dummy-target" id="异常处理流程"></a><h4>异常处理流程</h4>
<ul>
<li>异常处理准备，“精准异常”</li>
<li>确定异常来源，MIPS将异常相关状态存于Cause寄存器，由异常处理程序进行进一步查询和区分处理，同时对存储管理使用的地址转换异常等频繁发生的异常设置了专用的异常处理入口地址</li>
<li>保存执行状态</li>
<li>处理异常</li>
<li>恢复执行状态并返回，MIPS中异常返回的指令是<em>ERET</em></li>
</ul>
<a class="post-dummy-target" id="中断"></a><h4>中断</h4>
<p>分为可屏蔽中断(INT)和不可屏蔽中断(NMI)，可屏蔽中断通过协处理器SR进行屏蔽。中断的优先级方案为“更高优先级的中断发生时，可以抢占低优先级的中断处理过程”，因此，在执行中断中，需要带来对协处理器SR的修改，这个修改过程需要是原子性的，可以通过 <em><strong>信号量机制</strong></em> 来实现它的原子性。但设置信号量，在“测试并设置”过程中，获取信号量和设置信号量时所有共享访存都必须停止。</p>
<p>MIPS中，使用另一种机制，使用<em>LL</em>和<em>SC</em>指令来完成原子操作。</p>
<a class="post-dummy-target" id="中断传递机制"></a><h4>中断传递机制</h4>
<p>主要有两种形式：<em><strong>中断线</strong></em> 和 <em><strong>消息中断</strong></em></p>
<p>中断线简单，中断源不多时直接连到处理器引脚。消息中断以数据的方式在总线上传递，发中断就是往指定的地址写一个指定的数。</p>
<a class="post-dummy-target" id="存储管理"></a><h3>存储管理</h3>
<p>存储管理的作用和意义在于：</p>
<ul>
<li>隐藏和保护：用户态程序只能访问kuseg内存区域的数据，其他区域只能由核心态程序访问。</li>
<li>为程序分配连续的内存空间：存储管理部件（Memory Management Unit，简称MMU）可以由分散的物理也构建连续的虚拟内存空间</li>
<li>扩展地址空间：要访问所有4GB的物理内存空间，必须使用MMU进行转换</li>
<li>节约物理内存：有相同程序的多个副本在同时运行时，让这些副本使用相同的程序代码和只读数据。</li>
</ul>
<p>现代处理器通常包含一个转换后缓冲器（Translation Lookaside Buffer，简称TLB）来实现快速虚实地址的转换，TLB又称页表缓存或快表。（局部性原理）</p>
<a class="post-dummy-target" id="mips地址空间布局"></a><h4>MIPS地址空间布局</h4>
<p>32位MIPS处理器，有4GB的地址空间，划分如下：</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>地址范围</th>
<th>特性</th>
<th>访问权限</th>
</tr>
</thead>
<tbody>
<tr>
<td>kseg3</td>
<td>0xe0000000 ~ 0xffffffff</td>
<td>映射，缓存（TLB）</td>
<td>K</td>
</tr>
<tr>
<td>kseg2</td>
<td>0xc0000000 ~ 0xdfffffff</td>
<td>映射，缓存（TLB）</td>
<td>K/S</td>
</tr>
<tr>
<td>kseg1</td>
<td>0xa0000000 ~ 0xbfffffff</td>
<td>未映射，未缓存</td>
<td>K</td>
</tr>
<tr>
<td>kseg0</td>
<td>0x80000000 ~ 0x9fffffff</td>
<td>未映射，缓存（cfg）</td>
<td>K</td>
</tr>
<tr>
<td>useg</td>
<td>0x00000000 ~ 0x7fffffff</td>
<td>映射，缓存（TLB）</td>
<td>K/S/U</td>
</tr>
</tbody>
</table>
<p>以上空间具体特性，如何映射，何种Cache算法见书P55。</p>
<ul>
<li>useg ： 用户模式、监管模式和核心模式都可以访问，该段存放用户程序、动态链接库、程序堆栈。</li>
<li>kseg0 ： 该段存放内核代码、数据、异常处理入口</li>
<li>kseg1 ： 该段存放启动ROM和IO寄存器</li>
<li>kseg2 &amp; kseg3 ： 存放动态分配的内核数据</li>
</ul>
<a class="post-dummy-target" id="tlb的结构和使用"></a><h4>TLB的结构和使用</h4>
<p>MIPS的TLB采用全相联查找方式，通常设计为32项或64项，其结构如下：</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/TLB_Structure.png" alt="TLB表项结构" class="lazyload"><figcaption class="image-caption">TLB表项结构</figcaption></figure></p>
<ul>
<li>MASK : 用于控制TLB查找时控制VPN2的低位是否参与地址比较，因此MIPS的页可以在4KB至16MB之间可变</li>
<li>G：表示全局域，为1时关闭ASID匹配</li>
<li>ASID：用于区分不同进程的页表</li>
<li>PFN：物理帧号</li>
<li>C：表示对应物理页的Cashe算法</li>
<li>D：写控制位，1表示允许对该页写入</li>
<li>V：有效位，表示对应物理页是否在内存中</li>
</ul>
<p>需要注意的是：$\color{red}{每个TLB表项把两个连续的虚拟页映射为两个物理页}$</p>
<p>MIPS还定义了一组用于访问和控制TLB的控制寄存器，如下图：</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/RegistersAboutTLB.png" alt="TLB相关控制寄存器" class="lazyload"><figcaption class="image-caption">TLB相关控制寄存器</figcaption></figure></p>
<ul>
<li>Pagemask、EntryHi、EntryLo0和EntryLo1：他们与TLB内容完全一致，用于读写TLB表项</li>
<li>Index、Random和Wired：橙色框的这三个寄存器用于控制读写TLB哪个表项，Random会自动变化，它在Wired和TLB最大表项减一之间变换，<strong>0到Wired寄存器值之间的TLB不会被替换</strong>，可以存放一些常用表项。</li>
<li>EPC：保存被TLB异常打断的指令PC</li>
<li>BadVAddr：保存发生TLB异常的虚拟内存地址</li>
<li>Context：用于加速TLB重填异常</li>
<li>PTEBase：保存页表起始地址</li>
<li>BadVPN2：保存发生异常的虚拟页号</li>
</ul>
<p>关于<em>TLBR</em>、<em>TLBWI</em>、<em>TLBWR</em>和<em>TLBP</em>这四条指令，参考书P57。</p>
<p>CPU使用TLB时，将EntryHi中的ASID域和访存地址与TLB中每一项进行匹配，若命中则读出对应的PFN、C、D、V等内容，若不命中则法出TLB重填异常；若TLB命中但读出的V位为0，则发出TLB无效异常；若写TLB且TLB命中但读出的D位为0，则发出TLB修改异常，流程图见下：</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/TLB_Fail.png" alt="TLB异常流程" class="lazyload"><figcaption class="image-caption">TLB异常流程</figcaption></figure></p>
<a class="post-dummy-target" id="tlb异常处理"></a><h4>TLB异常处理</h4>
<p>这部分涉及了部分操作系统方面的东西，暂时跳过。可以看出硬件涉及和软件设计需要紧密配合，协同优化。</p>
<a class="post-dummy-target" id="软硬件协同"></a><h3>软硬件协同</h3>
<p>程序在指令系统上执行时需要遵循ABI（Application Binary Interface,应用程序二进制接口），ABI一般包含寄存器使用、函数调用、数据表示格式等约定，一下是三种MIPS函数调用规范：</p>
<ul>
<li>O32：传统的MIPS约定，仍广泛用于嵌入式工具链和32位Linux</li>
<li>N64：64位处理器使用的ABI，改变了指针和long型整数的宽度，改变了寄存器使用的约定和参数传递的方法</li>
<li>N32：相较于N64，指针和Long型整数的宽度为32位</li>
</ul>
<a class="post-dummy-target" id="mips-abi-整数寄存器约定"></a><h4>MIPS ABI 整数寄存器约定</h4>
<p>见书P62,这个更贴近汇编</p>
<a class="post-dummy-target" id="mips堆栈布局"></a><h4>MIPS堆栈布局</h4>
<p>叶子函数：不调用其他函数</p>
<p>非叶子函数：调用其他函数，需要在开始设置sp寄存器，为函数分配空间并标明嵌套调用的参数结构基址。</p>
<a class="post-dummy-target" id="本章其他"></a><h4>本章其他</h4>
<p>偏软，后期了解硬件再看。</p>
<a class="post-dummy-target" id="计算机组成原理和结构"></a><h3>计算机组成原理和结构</h3>
<a class="post-dummy-target" id="冯诺依曼结构"></a><h4>冯·诺依曼结构</h4>
<p>改进：</p>
<ul>
<li>从以存储器为中心改进到以运算器为中心</li>
<li>从单一控制改进到分散控制（初期时运算器，存储器，控制器，输入设备，输出设备用一个时钟信号，现在各设备间速度差异很大，异步控制）</li>
<li>从基于串行算法改进到适应并行算法，出现了流水线、超标量、向量、多核、对称多处理器、大规模并行</li>
<li>出现了适应特殊需要的专用计算机如GPU</li>
<li>非冯诺依曼计算机也取得一些成果，如数据驱动的数据流计算机、图规约计算机</li>
</ul>
<p>哈弗结构是冯诺依曼的变种，把程序和数据分开存储</p>
<a class="post-dummy-target" id="存储器"></a><h4>存储器</h4>
<p>现代内存基本采用同步随机存储器（SDRAM）实现，它具有以下特性：</p>
<ul>
<li>写操作会给后续的其他操作带来较打延迟，但连续的写操作可以流水执行</li>
<li>一行数据读出后，会保存再一组感应放大器中，如果继续访问该行数据，可以直接从感应放大器中读取</li>
<li>SDRAM包含的多个Bank是相互独立的，访问不同Bank的多个操作可以并行执行</li>
</ul>
<a class="post-dummy-target" id="北桥和南桥"></a><h4>北桥和南桥</h4>
<p>北桥：离CPU最近的芯片，主要负责控制显卡、内存与CPU之间的数据交换，向上连接处理器，向下连接南桥</p>
<p>南桥：主要负责硬盘、键盘以及各种对带宽要求较低的IO接口与内存、CPU之间的数据交换。</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/CPU_GPU_NorthBridge_SouthBridge.png" alt="CPU-GPU-北桥-南桥结构" class="lazyload"><figcaption class="image-caption">CPU-GPU-北桥-南桥结构</figcaption></figure></p>
<p>集成显卡指的是，GPU集成到北桥中。</p>
<ul>
<li>CPU-GPU-北桥-南桥结构：经典的结构</li>
<li>CPU-北桥-南桥三片结构：将GPU集成到北桥</li>
<li>CPU-弱北桥-南桥三片结构：将内存控制器集成到CPU</li>
<li>CPU-南桥两片结构：将GPU也集成到CPU（会影响CPU性能），中高端商用处理器采用两片结构</li>
<li>SoC单片结构：中低端及嵌入式领域的处理器</li>
</ul>
<a class="post-dummy-target" id="计算机总线接口技术"></a><h3>计算机总线接口技术</h3>
<a class="post-dummy-target" id="总线分类"></a><h4>总线分类</h4>
<ul>
<li>按数据传递方向：单向总线和双向总线（半双工/全双工）</li>
<li>按信号类型：并行总线和串行总线</li>
<li>按总线的物理位置：片上总线、内存总线、系统总线和IO总线
<ul>
<li>AXI总线（Advanced eXtensible Interface 高级可拓展接口），AXI协议是一个主从协议，包含5个通道：写请求、写数据、写响应、读请求、读响应。每个通道相互独立。AXI协议的一次完整读写过程称为一个总线事务，传输一个周期的数据称为一次传输。AXI协议使用双向握手协议。</li>
<li>AHB、ASB、APB总线</li>
</ul>
</li>
</ul>
<p>其他具体等需要时看具体的总线协议。</p>
<a class="post-dummy-target" id="简单运算器设计"></a><h3>简单运算器设计</h3>
<p>常见的加法器包括：</p>
<ul>
<li>行波进位加法器</li>
<li>先行进位加法器</li>
<li>跳跃进位加法器</li>
<li>进位选择加法器</li>
<li>进位递增加法器</li>
</ul>
<a class="post-dummy-target" id="一位全加器"></a><h4>一位全加器</h4>
<p>N位的加法器都是由一位全加器组合的（大概）。一位全加器如下图</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/Adder.jpg" alt="一位全加器" class="lazyload"><figcaption class="image-caption">一位全加器</figcaption></figure></p>
<p>可以看到一位全加器，有<em><strong>2到3级的门延迟</strong></em>。</p>
<a class="post-dummy-target" id="行波进位加法器"></a><h4>行波进位加法器</h4>
<p>N位进位加法器最简单的方法就是将N个一位全加器逐个串接起来，就像人一位位从后往前算竖式计算一样。这样的问题在于延迟过高，一个好的高性能通用CPU，在良好的流水线切分下，每级流水的延迟应该控制在20级门内，如果串联一位全加器，64位的行波进位加法器将有129级门延迟（主频爆炸）</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/Ripple_Carry_Adder.jpg" alt="行波进位加法器" class="lazyload"><figcaption class="image-caption">行波进位加法器</figcaption></figure></p>
<a class="post-dummy-target" id="先行进位并行进位加法器"></a><h4>先行进位（并行进位）加法器</h4>
<p>大致就是先把自己已有的两位A和B加起来，再根据进位来传播。一般加法器分块，4位一块，块内并行，块间串行。</p>
<p>如果更加追求加法器的速度，可以选择块内并行，块间并行，如下图：</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/Carry_Look-Ahead_Adder.png" alt="块内并行，块间并行" class="lazyload"><figcaption class="image-caption">块内并行，块间并行</figcaption></figure></p>
<a class="post-dummy-target" id="减法器"></a><h4>减法器</h4>
<p>A-B只要把B的输入相反一下，让后加法器一开始的进位为1即可</p>
<a class="post-dummy-target" id="比较器"></a><h4>比较器</h4>
<p>比较相等就两两并行比较相等，比大小就用减法器</p>
<a class="post-dummy-target" id="移位器"></a><h4>移位器</h4>
<p>这个操作比较出人意外，它是选择器组合而成的，根据前两位的状态选择移位后的结果。看图会更好一点。</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/Mover.png" alt="移位器" class="lazyload"><figcaption class="image-caption">移位器</figcaption></figure></p>
<a class="post-dummy-target" id="定点补码乘法器"></a><h3>定点补码乘法器</h3>
<a class="post-dummy-target" id="迭代式源码乘法器"></a><h4>迭代式源码乘法器</h4>
<p>就是模拟10进制的乘法过程，下面是4位乘4位的一个例子，以及硬件描述图：</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/ExampleOf4plus4.png" alt="4位乘4位例子" class="lazyload"><figcaption class="image-caption">4位乘4位例子</figcaption></figure></p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/Multiple1.png" alt="迭代式硬件源码乘法器" class="lazyload"><figcaption class="image-caption">迭代式硬件源码乘法器</figcaption></figure></p>
<p>问题在于，这是源码的乘法，计算机中用的补码，所以要改成补码乘。补码乘和普通的原码乘几乎一样（证明见书P149），区别再以下：</p>
<ul>
<li>补码乘法器中，加法，减法都为补码操作（需要进行8位的<strong>符号位拓展</strong>）</li>
<li>最后一次被累加的部分积需要使用补码减法</li>
</ul>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/Multiple2.png" alt="迭代式硬件补码乘法器" class="lazyload"><figcaption class="image-caption">迭代式硬件补码乘法器</figcaption></figure></p>
<a class="post-dummy-target" id="font-colorredbooth乘法器font"></a><h4><font color='red'>Booth乘法器</font></h4>
<p>由英国的Booth夫妇提出，原因是迭代式补码乘法器第N次乘法，需要挑出来用补码减法操作，需要实现一个额外的状态机，增加了硬件复杂度。</p>
<p>Booth一位乘的公式推导如下：
$$
(-y_7<em>2^7+y_6</em>2^6+&hellip;+y_1<em>2^1+y_0</em>2^0)
=(-y_7<em>2^7+(y_6</em>2^7-y_6<em>2^6)+(y_5</em>2^6-y_5<em>2^5)+&hellip;+(y_0</em>2^1-y_0<em>2^0)+(0</em>2^0))
=(y_6-y_7)*2^7+(y_5-y_6)*2^6+&hellip;+(y_0-y_1)*2^1+(y_{-1}-y_0)*2^0
$$
其中$y_{-1}$取值位0。这下公式变得规整，这个新公式被称为Booth一位乘算法。</p>
<p>但是一位乘仅仅解决了算法不规整的问题，计算N位的补码乘法，依然需要N-1次加法，因此重新对补码乘法公式进行变换，得到Booth两位乘算法：
$$
(-y_7<em>2^7+y_6</em>2^6+&hellip;+y_1<em>2^1+y_0</em>2^0)\<br>
=(-2<em>y_7</em>2^6+y_6<em>2^6+(y_5</em>2^6-2<em>y_5</em>2^4)+&hellip;+(y_1<em>2^2-2</em>y_1<em>2^0)+y_0</em>2^0+y_{-1}*2^0)\<br>
=(y_5+y_6-2y_7)*2^6+(y_3+y_4-2y_5)*2^4+&hellip;+(y_{-1}+y_0-2y_1)*2^0
$$
(公式可能打错，具体还要看书P151，就是前借一位，后借一位，然后前面借的要乘2，后面借的，后面要减去2)</p>
<p>Booth两位乘的规则如下：</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/Booth2Rule.png" alt="Booth两位乘规则" class="lazyload"><figcaption class="image-caption">Booth两位乘规则</figcaption></figure></p>
<p>使用Booth两位乘，只需要N/2次加法，需要使用N/2个时钟周期，大多数现代处理器也均采用该算法。对于Booth三位乘，有可能出现补码加3倍$[X]_{补}$的操作，2倍的可以通过左移1位来实现，3倍的值很难直接获得，需要再主循环前进行预处理，算出三倍的值，并用额外的触发器记录下来。所以，Booth两位乘更适合硬件实现。</p>
<p>Booth部分积的生成逻辑如下图：</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/8BitBoothPart.png" alt="Booth部分积生成逻辑" class="lazyload"><figcaption class="image-caption">Booth部分积生成逻辑</figcaption></figure></p>
<p>这个挺重要的，对下面华莱士树的了解有帮助，这是8位的定点乘法，可以看到，底下的被乘数有16位，这是通过移位操作实现的，代表每次左移两位。</p>
<a class="post-dummy-target" id="font-colorred华莱士树wallace-treefont"></a><h4><font color='red'>华莱士树（Wallace Tree）</font></h4>
<p>看完以后的感觉：</p>
<ul>
<li>利用全加器，把三个数缩成两个，8个数缩成2个最终只需要5步，数越多，越高效，因为是指数次的（分数为底，2/3左右）</li>
<li>可以流水线</li>
<li>每一级全加器生成的进位，都需要连接到另外华莱士树的更高级进位</li>
</ul>
<p>两种错误的8个数相加的一位华莱士树，其中右边那种，错误原因是不符合设计。</p>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/16BitMaltipler.png" alt="16位乘法器的示意图" class="lazyload"><figcaption class="image-caption">16位乘法器的示意图</figcaption></figure></p>
<ul>
<li>待补充1，2，3</li>
</ul>
<a class="post-dummy-target" id="自己动手写cpu"></a><h2>自己动手写CPU</h2>
<a class="post-dummy-target" id="流水线相关"></a><h3>流水线相关</h3>
<ul>
<li>结构相关：指令和数据共享一个存储器</li>
<li>数据相关：流水线中后面的指令依赖前面指令的结果
<ul>
<li><font color='red'>RAW: Read After Write</font>,RAW又有三种相关，相邻，隔一条指令，隔两条指令</li>
<li>WAR: Write After Read</li>
<li>WAW: Write After Write</li>
</ul>
</li>
<li>控制相关：跳转之类的</li>
</ul>
<p>隔两条指令的可以通过在回写时直接输出回写的值来解决。隔一条指令和指令相邻有以下三种解决方法：</p>
<ul>
<li>插入暂停周期</li>
<li>编译器调度</li>
<li><font color='red'>数据前推</font></li>
</ul>
<p><figure><img src="/svg/loading.min.svg" data-sizes="auto" data-src="/images/ComputerStructure/DataForward.png" alt="数据前推" class="lazyload"><figcaption class="image-caption">数据前推</figcaption></figure></p>
<a class="post-dummy-target" id="译码"></a><h3>译码</h3>
<p>本书译码模块大量冗余，后面重构需要改进。</p>
</div><div class="post-footer" id="post-footer">
    <div class="post-info">
        <div class="post-info-line">
            <div class="post-info-mod">
                <span>本文于 2021-01-16 更新</span>
            </div>
            <div class="post-info-license"></div>
        </div>
        <div class="post-info-line">
            <div class="post-info-md"></div>
            <div class="post-info-share"><span><a href="//twitter.com/share?url=%2f2021%2f01%2f%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA%25E4%25BD%2593%25E7%25B3%25BB%25E7%25BB%2593%25E6%259E%2584%2f&amp;text=%e8%ae%a1%e7%ae%97%e6%9c%ba%e4%bd%93%e7%b3%bb%e7%bb%93%e6%9e%84&amp;via=" target="_blank" title="分享到 Twitter">
            <i class="fab fa-twitter fa-fw"></i>
        </a><a href="//www.facebook.com/sharer/sharer.php?u=%2f2021%2f01%2f%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA%25E4%25BD%2593%25E7%25B3%25BB%25E7%25BB%2593%25E6%259E%2584%2f" target="_blank" title="分享到 Facebook">
            <i class="fab fa-facebook-square fa-fw"></i>
        </a><a href="//reddit.com/submit?url=%2f2021%2f01%2f%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA%25E4%25BD%2593%25E7%25B3%25BB%25E7%25BB%2593%25E6%259E%2584%2f&amp;title=%e8%ae%a1%e7%ae%97%e6%9c%ba%e4%bd%93%e7%b3%bb%e7%bb%93%e6%9e%84" target="_blank" title="分享到 Reddit">
            <i class="fab fa-reddit fa-fw"></i>
        </a><a href="//service.weibo.com/share/share.php?url=%2f2021%2f01%2f%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA%25E4%25BD%2593%25E7%25B3%25BB%25E7%25BB%2593%25E6%259E%2584%2f&amp;appkey=&amp;title=%e8%ae%a1%e7%ae%97%e6%9c%ba%e4%bd%93%e7%b3%bb%e7%bb%93%e6%9e%84" target="_blank" title="分享到 Weibo">
            <i class="fab fa-weibo fa-fw"></i>
        </a></span></div>
        </div>
    </div>

    <div class="post-info-more">
        <section><span class="tag">
                        <a href="/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84/"><i class="fas fa-tag fa-fw"></i>&nbsp;计算机体系结构</a>&nbsp;
                    </span></section>
        <section>
            <span><a href="javascript:window.history.back();">返回</a></span>&nbsp;|&nbsp;<span><a href="/">主页</a></span>
        </section>
    </div>

    <div class="post-nav"><a href="/2021/01/python%E5%8F%AF%E8%A7%86%E5%8C%96/" class="prev" rel="prev" title="Python可视化"><i class="fas fa-angle-left fa-fw"></i>Python可视化</a>
            <a href="/2021/02/2021%E7%BE%8E%E8%B5%9B/" class="next" rel="next" title="2021美赛">2021美赛<i class="fas fa-angle-right fa-fw"></i></a></div>
</div><div class="post-comment"></div>
    </article></div>
            </main><footer class="footer">
    <div class="copyright"><div class="copyright-line">由 <a href="https://gohugo.io/" target="_blank" rel="external nofollow noopener noreffer">Hugo</a> 强力驱动 | 主题 - <a href="https://github.com/dillonzq/LoveIt" target="_blank" rel="external nofollow noopener noreffer">LoveIt<i class="far fa-heart fa-fw"></i></a>
        </div>

        <div class="copyright-line"><i class="far fa-copyright fa-fw"></i><span itemprop="copyrightYear">2020 - 2021</span><span class="author" itemprop="copyrightHolder">&nbsp;<a href="/" target="_blank">ChenDong Zhu</a></span>&nbsp;|&nbsp;<span class="license"><a rel="license external nofollow noopener noreffer" href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank">CC BY-NC 4.0</a></span><span class="icp-splitter">&nbsp;|&nbsp;</span><br class="icp-br"/>
                <span class="icp"><a href="http://beian.miit.gov.cn">苏ICP备2021012540号</a></span></div>
    </div>
</footer></div><a href="#" class="dynamic-to-top" id="dynamic-to-top" data-scroll>
            <span>&nbsp;</span>
        </a><script src="/js/lib/jquery/jquery.slim.min.js"></script><script src="/js/lib/lazysizes/lazysizes.min.js"></script><script src="/js/lib/smooth-scroll/smooth-scroll.polyfills.min.js"></script><script>window.scroll = new SmoothScroll('[data-scroll]', {speed: 300, speedAsDuration: true});</script><link rel="stylesheet" href="/css/lib/katex/katex.min.css"><script src="/js/lib/katex/katex.min.js"></script><script defer src="/js/lib/katex/auto-render.min.js"></script><link rel="stylesheet" href="/css/lib/katex/copy-tex.min.css"><script defer src="/js/lib/katex/copy-tex.min.js"></script><script defer src="/js/lib/katex/mhchem.min.js"></script><script>
        document.addEventListener("DOMContentLoaded", function () {
            renderMathInElement(document.body, {
                delimiters: [
                    { left: "$$", right: "$$", display: true },
                    { left: "\\(", right: "\\)", display: false },
                    { left: "\\[", right: "\\]", display: true },{ left: "$", right: "$", display: false },]
            });
        });
    </script>
    <script src="https://eqcn.ajz.miesnfu.com/wp-content/plugins/wp-3d-pony/live2dw/lib/L2Dwidget.min.js"></script>

    <script>
        var sUserAgent = navigator.userAgent.toLowerCase();
        if (/ipad|iphone|midp|rv:1.2.3.4|ucweb|android|windows ce|windows mobile/.test(sUserAgent)){
            
        }
        else{
            L2Dwidget.init({
                
                "model": {
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                                
                    jsonPath: "/data/Shinomiya_Kaguya/model.model.json",
                    "scale": 1
                },
                
                "display": {
                    "position": "left",
                    "width": 150,
                    "height": 300,
                    "hOffset": 0,
                    "vOffset": 0
                },
                "mobile": {
                    "show": true,
                    "scale": 0.5
                },
                "react": {
                    "opacityDefault": 1,
                    "opacityOnHover": 0.2
                }
            });
                function changebottom() {
                            var canvas_temp = document.getElementById("live2dcanvas");
            canvas_temp.style="position: fixed; opacity: 1; left: 0px; bottom: -100px; z-index: 99999; pointer-events: none;";
                }

            window.onload=changebottom;
        }


    </script><script src="/js/blog.min.js"></script>
</body>
</html>